package pers.whj.handler;

public class Handler {
    private final Looper mLooper;
    private final MessageQueue mQueue;
    private final Callback mCallback;

    public interface Callback {
        boolean handleMessage(Message msg);
    }

    public Handler() {
        this((Callback) null);
    }

    public Handler(Looper looper) {
        this(looper, null);
    }

    public Handler(Callback callback) {
        this(Looper.myLooper(), callback);
    }

    public Handler(Looper looper, Callback callback) {
        if (looper == null) {
            throw new RuntimeException("Can't create handler inside thread that has not called Looper.prepare()");
        }
        mLooper = looper;
        mCallback = callback;
        mQueue = looper.mQueue;
    }

    public void handleMessage(Message msg) {
    }

    public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            msg.callback.run();
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }

    public final boolean hasMessages(int what) {
        return mQueue.hasMessages(this, what, null);
    }

    public final boolean hasMessages(int what, Object obj) {
        return mQueue.hasMessages(this, what, obj);
    }

    public final Looper getLooper() {
        return mLooper;
    }

    public final Message obtainMessage(int what, int arg1, int arg2, Object obj) {
        return Message.obtain(this, what, arg1, arg2, obj);
    }

    public final Message obtainMessage(int what, int arg1, int arg2) {
        return Message.obtain(this, what, arg1, arg2, null);
    }

    public Message obtainMessage() {
        return Message.obtain(this);
    }

    public Message obtainMessage(int what) {
        return Message.obtain(this, what);
    }

    public Message obtainMessage(int what, Object obj) {
        return Message.obtain(this, what, 0, 0, obj);
    }

    public final boolean sendMessageAtFrontOfQueue(Message msg) {
        msg.when = System.currentTimeMillis();
        return mQueue.enqueueMessage(msg);
    }

    public final boolean sendEmptyMessage(int what) {
        return sendEmptyMessageDelayed(what, 0);
    }

    public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
        Message msg = Message.obtain(this);
        msg.what = what;
        return sendMessageDelayed(msg, delayMillis);
    }

    public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
        Message msg = Message.obtain(this);
        msg.what = what;
        return sendMessageAtTime(msg, uptimeMillis);
    }

    public final boolean sendMessage(Message msg) {
        return sendMessageDelayed(msg, 0);
    }

    public final boolean sendMessageDelayed(Message msg, long delayMillis) {
        delayMillis = Math.max(delayMillis, 0);
        return sendMessageAtTime(msg, System.currentTimeMillis() + delayMillis);
    }

    public boolean sendMessageAtTime(Message msg, long time) {
        msg.when = time;
        return mQueue.enqueueMessage(msg);
    }

    public final boolean postAtFrontOfQueue(Runnable r) {
        return sendMessageAtFrontOfQueue(getPostMessage(r));
    }

    public final boolean postAtTime(Runnable r, Object token, long time) {
        return sendMessageAtTime(getPostMessage(r, token), time);
    }

    public boolean post(Runnable r) {
        return sendMessage(getPostMessage(r));
    }

    public boolean postDelayed(Runnable r, long delayMillis) {
        return sendMessageDelayed(getPostMessage(r), delayMillis);
    }

    public boolean postAtTime(Runnable r, long time) {
        return sendMessageAtTime(getPostMessage(r), time);
    }

    public final void removeCallbacks(Runnable r) {
        mQueue.removeMessages(this, r, null);
    }

    public final void removeCallbacks(Runnable r, Object token) {
        mQueue.removeMessages(this, r, token);
    }

    public final void removeMessages(int what) {
        mQueue.removeMessages(this, what, null);
    }

    public final void removeMessages(int what, Object obj) {
        mQueue.removeMessages(this, what, obj);
    }

    public final void removeCallbacksAndMessages(Object token) {
        mQueue.removeCallbacksAndMessages(this, token);
    }

    private Message getPostMessage(Runnable r) {
        Message msg = Message.obtain(this);
        msg.callback = r;
        return msg;
    }

    private Message getPostMessage(Runnable r, Object token) {
        Message msg = Message.obtain(this);
        msg.callback = r;
        msg.obj = token;
        return msg;
    }
}